home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
-
- MODULE
- HL.c
-
- DESCRIPTION
- ``Hierachic Lists''
-
- NOTES
-
- BUGS
- none known - never tested
-
- TODO
- connections: Connect, RemoveLock, Notify
-
- EXAMPLES
-
- SEE ALSO
-
- INDEX
-
- HISTORY
- 22-11-94 b_noll created
-
- ******************************************************************************/
-
-
- /**************************************
- Includes
- **************************************/
-
- #include "HL.h"
- #include "Definitions.h"
- #include "xdme_base.h"
-
- #include <stdlib.h>
- #include <string.h>
-
-
- #include <intuition/classes.h>
-
- /**************************************
- Global Variables
- **************************************/
-
- extern int NodeNodeComparison(void *, void *);
- extern int NodeStringComparison(void *, const UBYTE *);
-
- /**************************************
- Internal Defines & Structures
- **************************************/
-
- #define HL_OK 0
- #define HL_ERROR 1
- #define HL_NOMEM 2
- #define HL_NOLIST 3
- #define HL_DUPTREENODE 4
-
-
- struct Locker {
- struct SNode Node;
- struct Locker*Base;
- struct HNode *Partner;
- ULONG Attr;
- }; /* struct */
-
- #define SCAN void *
- #define FIND void *
-
- /**************************************
- Internal Variables
- **************************************/
-
- struct HNode *HL_Root = NULL;
-
- /**************************************
- Internal Prototypes
- **************************************/
-
-
- /**************************************
- Macros
- **************************************/
-
-
- /**************************************
- Implementation
- **************************************/
-
- #if 0
- #include <proto/exec.h>
- static APTR allocmem (int n)
- {
- return AllocVec (n, 0);
- } /* malloc */
-
- static void freemem (APTR n)
- {
- FreeVec (n);
- } /* free */
- #else
- #define allocmem malloc
- #define freemem free
- #endif
-
-
- #if 0
- struct LockerNode {
- struct SNode Node;
- struct Locker *Base;
- APTR Partner;
- ULONG Attr;
- }; /* struct LockerNode */
-
- struct Locker {
- struct LockerNode Parts[2];
- ULONG Flags;
- }; /* struct Locker */
-
- static __inline struct LockerNode *PartnerNode(struct LockerNode *n) {
- int is_Header = (n->Base->Parts == n)? 1: 0;
- return n->Base->Parts + is_Header;
- } /* PartnerNode */
-
- static void PBL__DropLocks (struct LockerNode *n, struct HNode *o) {
- int is_Header = (n->Base->Parts == n)? 1: 0;
-
- /* ---- we avoid endless loops by removing the node from our own
- ** list of locks before notifying the partner, and by checking
- ** if we have this node before sending ... */
-
- if (SLL_Remove (&o->Locks, &n->Node)) {
- DoDispatch (n->Partner, PB_CONNECT, PBA_Resolve, PartnerNode(n));
-
- /* ---- Only one of the 2 Partners may free the Locker */
- if (is_Header)
- free (n->Base);
- } /* if */
- } /* PBL__DropLocks */
-
- static void PBL__NotifyLocks (struct LockerNode *n, struct PB_Msg *m) {
- int is_Header = (n->Base->Parts == n)? 1: 0;
-
- if (m->Attr == n->Attr)
- if (is_Header) // (IsSendingPart(n))
- DoSet (n->Partner, PartnerNode(n)->Attr, m->Value);
- } /* PBL_NotifyLocks */
-
-
- UNVOLLSTAENDIG - BRAUCHT PARTNER INITIALISIERUNG!
-
-
- /* ---- send a notification */
-
- ULONG HL_Notify (struct GadNode *gadget, ULONG attr, APTR value, struct HNode *base) {
- return GTB_Notify(gadget, attr, value, base);
- } /* HL_Notify */
-
-
- /* ---- remove a certain lock from base */
-
- static void HL_RemoveLock (struct Locker *l, struct HNode *base)
- {
- SLL_Remove (&base->Locks, &l->Node);
- HL_Notify (l->Partner, l->Attr, NULL, NULL);
- DISPOSE(l);
- } /* HL_RemoveLock */
-
-
- /* ---- build a connection between base and its partner */
-
- ULONG HL_Connect (struct HNode *base, struct HNode *partner, ULONG attr)
- {
- struct Locker *l, *pl;
- if (attr != N_NAME && attr != N_LIST && attr != N_VALUE)
- return 0;
-
- if (l = malloc (sizeof (*l))) {
- bzero(l, sizeof (*l));
- SLL_AddHead(&base->Locks, &l->Node);
- l->Partner = partner;
- l->Attr = attr;
-
- //if (attr == N_NAME)
- // HL_Notify(partner, attr, base->Name, base);
-
- //if (attr == N_VALUE)
- // HL_Notify(partner, attr, base->Value, base);
-
- //if (attr == N_LIST)
- // HL_Notify(partner, attr, &base->Subs, base);
-
- return 1;
- } /* if */
- return 0;
- } /* HL_Connect */
-
-
- AB HIER OK (HOFFE ICH)
-
- #else
- void HL_RemoveLock (struct Locker *l, struct HNode *base);
- ULONG HL_Notify (struct HNode *gadget, ULONG attr, APTR value, struct HNode *base);
- #endif
-
-
- /* ---- Find a Lock between base and its partner */
-
- static struct Locker *HL_FindLock (struct HNode *base, APTR partner)
- {
- struct Locker *l;
- if (base)
- for (l = (APTR)base->Locks.Head; l; l = (APTR)l->Node.Succ) /* 1 */
- if (l->Partner == partner)
- return l;
- return NULL;
- } /* HL_FindLock */
-
-
- /* ---- remove all connections between base and its partner */
-
- ULONG HL_Disconnect (struct HNode *base, struct HNode *partner)
- {
- struct Locker *l;
- if (base && partner)
- while ((l = HL_FindLock(base, partner)))
- HL_RemoveLock(l, base);
- return HL_OK;
- } /* HL_Disconnect */
-
-
-
- /* ---- strip all locks from base */
-
- static void HL_RemoveLocks (struct HNode *base)
- {
- SLL_Scan(&base->Locks, (SCAN)HL_RemoveLock, base);
- } /* HL_RemoveLocks */
-
-
-
- /* ---- notify all partners which are listening 2 attr */
-
- static void HL_NotifyLocks (struct HNode *base, ULONG attr, APTR value)
- {
- struct Locker *l;
- //printf (" StratNotificaton %d %08lx\n", attr, value);
- if (base) {
- base->Flags |= HLF_PRIVATESET;
- for (l = (APTR)base->Locks.Head; l; l = (APTR)l->Node.Succ) {
- //printf (" ... %d ", l->Attr);
- if (l->Attr == attr)
- HL_Notify (l->Partner, attr, value, base);
- }
- base->Flags &= ~HLF_PRIVATESET;
- }
- } /* HL_NotifyLocks */
-
-
-
-
-
-
-
-
- /* ---- get the Value instance data of a HNode */
-
- //static
- struct HLAValue *HL_InstValue (struct HNode *base)
- {
- ULONG len = sizeof (*base);
-
- if (!(base->Flags & HLF_VALUE))
- return NULL;
-
- return (struct HLAValue *)(len + (ULONG)base);
- } /* HL_InstValue */
-
-
- /* ---- get the SubsList instance data of a HNode */
-
- //static
- struct HLASubs *HL_InstSubs (struct HNode *base)
- {
- ULONG len = sizeof (*base);
-
- if (!(base->Flags & HLF_SUBCARRIER) || (base->Flags & HLF_TREE))
- return NULL;
-
- if (base->Flags & HLF_VALUE)
- len += sizeof (struct HLAValue);
-
- return (struct HLASubs *)(len + (ULONG)base);
- } /* HL_InstSubs */
-
-
- /* ---- get the SubsTree instance data of a HNode */
-
- static struct HLATree *HL_InstTree (struct HNode *base)
- {
- ULONG len = sizeof (*base);
-
- if (!(base->Flags & HLF_TREE))
- return NULL;
-
- if (base->Flags & HLF_VALUE)
- len += sizeof (struct HLAValue);
-
- return (struct HLATree *)(len + (ULONG)base);
- } /* HL_InstTree */
-
-
- /* ---- change the parent slot of a HNode */
-
- static void HL_SetParent (struct HNode *n, struct HNode *parent) {
- n->Parent = parent;
- } /* HL_SetParent */
-
-
- /* **** Lock the SubsList of a HNode for Manipulation */
-
- struct DList *HL_LockSubs (struct HNode *base)
- {
- struct HLASubs *s;
-
- if (!base )
- return NULL;
-
- if (!base || !(base->Flags & HLF_SUBCARRIER) || (base->Flags & HLF_TREE))
- return NULL;
-
- if (!base->BlockCnt++)
- if (base->Locks.Head)
- HL_NotifyLocks (base, HLA_Labels, (void *)~0L);
-
- s = HL_InstSubs(base);
- //if (!base->BlockCnt++)
- // DLL_Scan (&s->Subs, (SCAN)HL_SetParent, NULL);
-
- return &s->Subs;
- } /* HL_LockSubs */
-
-
- /* **** Unlock a previously locked SubsList */
-
- ULONG HL_UnlockSubs (struct HNode *base)
- {
- struct HLASubs *s;
-
- if (!base || !(base->Flags & HLF_SUBCARRIER) || (base->Flags & HLF_TREE))
- return HL_NOLIST;
-
- s = HL_InstSubs(base);
-
- if (!--base->BlockCnt)
- DLL_Scan (&s->Subs, (SCAN)HL_SetParent, base);
-
- if (!base->BlockCnt)
- if (base->Locks.Head)
- HL_NotifyLocks (base, HLA_Labels, &s->Subs);
- } /* HL_UnlockSubs */
-
-
- /* ---- append a new member 2 base (notifying in Lists) */
-
- ULONG HL_AddMember (struct HNode *base, struct HNode *member, struct HNode *where)
- {
- struct HLATree *t;
- struct HLASubs *s;
-
- if (!base || !member )
- return HL_ERROR;
-
- if (base->Flags & HLF_TREE) {
- t = HL_InstTree(base);
- if (AVL_Find(&t->Subs, NodeStringComparison, member->Name))
- return HL_DUPTREENODE;
-
- AVL_Append (&t->Subs, NodeNodeComparison, (struct TreeNode *)member);
- member->Parent = base;
- return HL_OK;
- } /* if */
-
- if (!(base->Flags & HLF_SUBCARRIER))
- return HL_NOLIST;
-
- if (!base->BlockCnt++)
- if (base->Locks.Head)
- HL_NotifyLocks (base, HLA_Labels, (void *)~0L);
-
- s = HL_InstSubs(base);
- if (!where)
- DLL_AddTail (&s->Subs, &member->Node);
- else
- DLL_AddBehind (&s->Subs, &member->Node, &where->Node);
- member->Parent = base;
-
- if (!--base->BlockCnt)
- if (base->Locks.Head)
- HL_NotifyLocks (base, HLA_Labels, &s->Subs);
- return HL_OK;
- } /* HL_AddMember */
-
-
- /* ---- remove a member from base (notifying in lists) */
-
- ULONG HL_RemMember (struct HNode *base, struct HNode *member)
- {
- struct HLATree *t;
- struct HLASubs *s;
-
- if (!base || !member )
- return HL_ERROR;
-
- if (base->Flags & HLF_TREE) {
- t = HL_InstTree(base);
- AVL_Remove (&t->Subs, NodeNodeComparison, (struct TreeNode *)member);
- member->Parent = NULL;
- return HL_OK;
- } /* if */
-
- if (!(base->Flags & HLF_SUBCARRIER))
- return HL_NOLIST;
-
- if (!base->BlockCnt++)
- if (base->Locks.Head)
- HL_NotifyLocks (base, HLA_Labels, (void *)~0L);
-
- s = HL_InstSubs(base);
- DLL_Remove (&s->Subs, &member->Node);
- member->Parent = NULL;
-
- if (!--base->BlockCnt)
- if (base->Locks.Head)
- HL_NotifyLocks (base, HLA_Labels, &s->Subs);
- return HL_OK;
- } /* HL_RemMember */
-
-
- /* **** free all HL data of a node like structure */
-
- Prototype ULONG HL_Uninit (struct HNode *n);
- ULONG HL_Uninit (struct HNode *n)
- {
- struct HLATree *t;
- struct HLASubs *s;
- struct HLAValue *v;
-
- if (!n)
- return HL_ERROR;
-
- if (n->Parent) {
- ULONG rv;
- rv = HL_RemMember (n->Parent, n);
- if (rv != HL_OK)
- return rv;
- } /* if */
-
- if (n->Locks.Head)
- HL_RemoveLocks (n);
-
- if (n->Flags & HLF_TREE) {
- t = HL_InstTree(n);
- AVL_ScanTree (&t->Subs, (SCAN)HL_SetParent, AVL_SCAN_INFIX);
- AVL_FreeTree (&t->Subs, (SCAN)HL_Dispose);
- } else if (n->Flags & HLF_SUBCARRIER) {
- s = HL_InstSubs(n);
- DLL_Scan (&s->Subs, (SCAN)HL_Dispose, NULL);
- }
-
- if (n->Flags & HLF_VALUE) {
- v = HL_InstValue(n);
- if (v->Value)
- free (v->Value);
- }
-
- if (n->Name)
- free (n->Name);
-
- return HL_OK;
- } /* HL_Uninit */
-
-
- /* **** prepare the HL part of a node like structure */
-
- Prototype ULONG HL_Init (struct HNode *n, const UBYTE *name, struct HNode *parent, UWORD flags);
- ULONG HL_Init (struct HNode *n, const UBYTE *name, struct HNode *parent, UWORD flags)
- {
- struct HLATree *t;
- struct HLASubs *s;
- struct HLAValue *v;
-
- n->Name = strdup (name);
- n->Locks.Head = NULL;
- n->Parent = NULL;
- n->Flags = flags;
-
- if (flags & HLF_TREE) {
- t = HL_InstTree(n);
- AVL_Init (&t->Subs);
- } else if (flags & HLF_SUBCARRIER) {
- s = HL_InstSubs(n);
- DLL_Init (&s->Subs);
- }
-
- if (flags & HLF_VALUE) {
- v = HL_InstValue(n);
- v->Value = strrep (NULL, "");
- }
-
- if ( !n->Name || ((flags & HLF_VALUE) && !v->Value) ) {
- HL_Uninit (n);
- return HL_NOMEM;
- } /* if */
-
- if (parent) {
- ULONG rv;
- if ((rv = HL_AddMember (parent, n, NULL)) != HL_OK) {
- HL_Uninit (n);
- return rv;
- } /* if */
- } /* if */
-
- return HL_OK;
- } /* HL_Init */
-
-
- /* **** dispose a HNode entry (safe) */
-
- Prototype ULONG HL_Dispose (struct HNode *n);
- ULONG HL_Dispose (struct HNode *n)
- {
- ULONG rv;
- if ((rv = HL_Uninit(n)) == HL_OK)
- freemem (n);
- return rv;
- } /* HL_Dispose */
-
-
- /* **** create a new HNode entry */
-
- struct HNode *HL_New (const UBYTE *name, struct HNode *parent, UWORD flags)
- {
- struct HNode *n;
- ULONG rv;
- ULONG len = sizeof (struct HNode);
-
- if (flags & HLF_TREE)
- len += sizeof (struct HLATree);
- else if (flags & HLF_SUBCARRIER)
- len += sizeof (struct HLASubs);
-
- if (flags & HLF_VALUE)
- len += sizeof(struct HLAValue);
-
- if (n = allocmem (len)) {
- bzero (n, len);
- if ((rv = HL_Init(n, name, parent, flags)) != HL_OK) {
- freemem (n);
- return NULL;
- } /* if */
- } /* if */
- return n;
- } /* HL_New */
-
-
- /* **** create a new toplevel list with systemattribute */
-
- struct HNode * HL_SystemList (const UBYTE *name)
- {
- if (!HL_Root)
- HL_Root = HL_New("*Root*", NULL, HLF_SUBCARRIER);
- if (!HL_Root)
- return NULL;
-
- return HL_New (name, HL_Root, HLF_SUBCARRIER|HLF_SYSNODE);
- } /* HL_SystemList */
-
-
- /* **** lock, scan & unlock a list */
-
- void HL_Scan (struct HNode *n, void (*scan)(struct HNode*, void*, int), void *userdata)
- {
- struct DList *l;
- if ((l = HL_LockSubs (n))) {
- DLL_Scan (l, (SCAN)scan, userdata);
- HL_UnlockSubs(n);
- //} else if ((t = HL_InstTree (n)))
- // AVL_ScanTree (&t->Subs, (SCAN)scan, AVL_SCAN_POSTFIX, userdata);
- } /* if */
- } /* HL_Scan */
-
- struct HNode *HL_Find (struct HNode *n, int (*find)(struct HNode*, void*, int), void *userdata)
- {
- struct HLASubs *s;
- struct HLATree *t;
-
- if ((s = HL_InstSubs (n)))
- return (struct HNode *)DLL_Find (&s->Subs, (FIND)find, userdata);
- else if ((t = HL_InstTree (n)))
- return (struct HNode *)AVL_Find (&t->Subs, (FIND)find, userdata);
- else
- return NULL;
- } /* HL_Find */
-
-
-
-
- #ifndef freemem
- void _STD_10000_HL_Exitus (void) {
- HL_Dispose(HL_Root);
- } /* HL_Exitus */
- #endif
-
- /******************************************************************************
- ***** END HL.c
- ******************************************************************************/
-
- #if 0
-
- static ULONG HL__ClassSize (struct HClass *c) {
- ULONG s = 0;
- while (c) {
- s += c->Size;
- c = c->Superclass;
- } /* while */
- return s;
- } /* HL__ClassSize */
-
- static ULONG HL__Dispatcher (struct HNode *n, struct HClass *class, ULONG *msg)
- {
- switch (*msg) {
- case OM_DISPOSE:
- HL_Uninit(n);
- free (n);
- break;
- case OM_NEW:
- if ((n = malloc(HL__ClassSize((struct HClass *)n)))) {
- if (HL_Init(n, (UBYTE *)*(msg+1), (struct HNode *)*(msg+2), *(msg+3)) == HL_OK)
- return (ULONG)n;
- free (n);
- } /* if */
- return NULL;
- } /* switch */
- return 0;
- } /* HL__Dispatcher */
-
-
- ULONG HL__Coerce (struct HNode *n, struct HClass *c, ULONG *msg)
- {
- return c->Dispatcher(n, c, msg);
- } /* HL__Coerce */
-
- ULONG HL__Method (struct HNode *n, ULONG *msg)
- {
- return HL__Coerce(n, n->Class, msg);
- } /* HL_Method */
-
- struct HClass HRoot = {
- HL__Dispatcher,
- sizeof (struct HNode) + sizeof (struct HLAValue) + sizeof (struct HLASubs),
- NULL
- };
-
- struct HClass HLSubCarrier = {
- HL__Dispatcher,
- sizeof (struct HLASubs),
- &HRoot
- };
-
- struct HClass HLValCarrier = {
- HL__Dispatcher,
- sizeof (struct HLAValue),
- &HLSubCarrier
- };
-
- struct HNode *HL__New (struct HClass *c, UBYTE *name, struct HNode *parent, WORD flags) {
- ULONG new[] = { OM_NEW, 0,0,0,0 };
- new[1] = (ULONG)name;
- new[2] = (ULONG)parent;
- new[3] = flags;
- return (struct HNode *)HL__Coerce ((struct HNode *)c, c, new);
- }
-
- ULONG HL__SetN (struct HNode *n, ...)
- {
- ULONG set[] = { OM_SET, NULL };
- set[1] = (ULONG)((&n)+1);
- return HL__Method(n, set);
- } /* HL__SetN */
-
- ULONG HL__SetS (struct HNode *n, ULONG attr, ULONG value)
- {
- return HL__SetN (n, attr, value, TAG_DONE);
- } /* HL__SetS */
-
- void HL__GetS (struct HNode *n, ULONG attr, ULONG *value)
- {
- ULONG get[] = { OM_GET, 0, 0 };
- get[1] = attr;
- get[2] = (ULONG)value;
- HL__Method(n, get);
- } /* HL__GetS */
-
- void HL__Dispose (struct HNode *n)
- {
- ULONG dispose = OM_DISPOSE;
- HL__Method (n, &dispose);
- } /* HL_Dispose */
-
- #endif
-